﻿using Furion;
using Furion.FriendlyException;
using Microsoft.Extensions.Caching.Memory;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.DataProtection.KeyManagement;

namespace OnWork.DataCenter.Utils.Caches
{
    /// <summary>
    /// 内存缓存帮助类
    /// </summary>
    public class MemoryCacheUtil
    {
        /// <summary>
        /// 缓存
        /// </summary>
        private static IMemoryCache _cache = App.GetService<IMemoryCache>();

        /// <summary>
        /// 保存关键字
        /// </summary>
        private static ConcurrentDictionary<string,string> _keys = new ConcurrentDictionary<string,string>();

        /// <summary>
        /// 获取或创建缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public static T GetOrCreate<T>(string key, Func<ICacheEntry, T> factory)
        {
            //获取缓存 不存在则添加key
            if (!_cache.TryGetValue(key, out object result))
            {
                using ICacheEntry entry = _cache.CreateEntry(key);
                result = factory(entry);
                _keys.TryAdd(key,"");
                entry.Value = result;
            }
            return (T)result;
        }

        /// <summary>
        /// 获取或创建缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public async static Task<T> GetOrCreateAsync<T>(string key, Func<ICacheEntry, Task<T>> factory)
        {
            if (!_cache.TryGetValue(key, out object result))
            {
                using ICacheEntry entry = _cache.CreateEntry(key);
                result = await factory(entry).ConfigureAwait(false);
                _keys.TryAdd(key, "");
                entry.Value = result;
            }
            return (T)result;
        }

        /// <summary>
        /// 获取或创建缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async static Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> value)
        {
            return await GetOrCreateAsync(key, async entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(20); //设置绝对过期时间
                return await value.Invoke();
            });
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public static T GetOrCreate<T>(string key, Func<T> value)
        {
            return GetOrCreate(key, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(20); //设置绝对过期时间
                return value.Invoke();
            });
        }

        public static void Remove(string key)
        {
            _cache.Remove(key);
        }

        /// <summary>
        /// 移除缓存 模糊匹配
        /// </summary>
        /// <param name="keys">包含的字段</param>
        public static void Removes(string keys)
        {
            //为空则退出
            if (string.IsNullOrEmpty(keys) || _keys == null)
            {
                return;
            }

            var delKeys = _keys.Keys.Where(x => x.Contains(keys)).ToList();

            if (delKeys != null && _keys.Count > 0)
            {
                foreach (var key in delKeys)
                {
                    //移除对象
                    _keys.TryRemove(key, out _);
                    _cache.Remove(key);
                }
            }
        }
    }
}